﻿using System;
using System.ComponentModel;
using System.Workflow.Activities;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Compiler;
using Argos.Diagnostics;
using System.Diagnostics;

namespace Argos.Workflows
{
	/// <summary>
	/// Defines a state machine workflow that monitors a target for changes.
	/// </summary>
	[DisplayName("Change Monitor")]
	[Description("Monitors a target for changes, and sends alerts whenever a change is encountered.")]
    public sealed partial class TargetChangeMonitoringWorkflow : TargetMonitoringWorkflowBase , ITargetChangeMonitoringWorkflow
    {

		#region #ctor: public TargetChangeMonitoringWorkflow()

		/// <summary>
		/// Creates a new instance of the class.
		/// </summary>
		public TargetChangeMonitoringWorkflow()
		{
			InitializeComponent();
		}

		#endregion



		#region public object CurrentTestState { get; set; }

		public static readonly DependencyProperty CurrentTestStateProperty = DependencyProperty.Register("CurrentTestState", typeof(object), typeof(TargetChangeMonitoringWorkflow));

		[Description("Specifies the test state for the test of the target that this monitoring workflow represents.")]
		[ValidationOption(ValidationOption.Optional)]
		[Browsable(false)]
		public object CurrentTestState
		{
			get { return this.GetValue(CurrentTestStateProperty); }
			set { this.SetValue(CurrentTestStateProperty, value); }
		}

		#endregion

		#region public object PreviousTestState { get; set; }

		public static readonly DependencyProperty PreviousTestStateProperty = DependencyProperty.Register("PreviousTestState", typeof(object), typeof(TargetChangeMonitoringWorkflow));

		[Browsable(false)]
		public object PreviousTestState
		{
			get { return this.GetValue(PreviousTestStateProperty); }
			set { this.SetValue(PreviousTestStateProperty, value); }
		}

		#endregion



		private void Condition_IsTargetChanged(object sender, ConditionalEventArgs e)
		{
			e.Result = ((ITargetChangeMonitoringWorkflow)this).IsChanged(this.CurrentTestState, this.PreviousTestState);
		}

		private void Condition_IsTargetDisabled(object sender, ConditionalEventArgs e)
		{
			e.Result = ((ITargetMonitoringWorkflow)this).TargetDisabled;

			if (e.Result)
			{
				Tracer.TraceData(TraceEventType.Warning, 0, "Monitoring is disabled for current target.", Tracer.CreateData("TargetId", this.TargetId), Tracer.CreateData("InstanceId", this.WorkflowInstanceId));
			}
		}

		private void Condition_IsTargetPaused(object sender, ConditionalEventArgs e)
		{
			e.Result = this.IsPaused();

			if (e.Result)
			{
				Tracer.TraceData(TraceEventType.Warning, 0, "Monitoring is paused for current target.", Tracer.CreateData("TargetId", this.TargetId), Tracer.CreateData("InstanceId", this.WorkflowInstanceId));
			}
		}

		private void OnInitializeTestDelay(object sender, EventArgs e)
		{
			this.TestDelay1.TimeoutDuration = ((ITargetMonitoringWorkflow)this).TestInterval;
		}



		void ITargetChangeMonitoringWorkflow.HandleChange(object currentState, object previousState)
		{
			
		}

		bool ITargetChangeMonitoringWorkflow.IsChanged(object currentState, object previousState)
		{
			if (null != currentState && null != previousState && currentState is Array && previousState is Array)
			{
				Array arr1 = (Array)currentState;
				Array arr2 = (Array)previousState;

				if (arr1.Length != arr2.Length)
				{
					return true;
				}

				for (int i = 0; i < arr1.Length; i++)
				{
					if (!object.Equals(arr1.GetValue(i), arr2.GetValue(i)))
					{
						return true;
					}
				}
			}
			else
			{
				return !object.Equals(currentState, previousState);
			}

			return false;
		}
		
	}
}
